#include <buola/gui/x11/auto.h>

#include <buola/gl.h>

#include <buola/gui/x11/cglxexposehelper.h>
#include <buola/gui/cwindow.h>
#include <buola/gui/cphysicalwindow.h>
#include <buola/image/csurface.h>
#include <buola/image/cgc.h>
#include <buola/mat/transformations.h>
#include <buola/gui/x11/cx11window.h>
#include <buola/gui/x11/cglxcontext.h>

#include <buola/gl.h>

namespace buola { namespace gui { namespace x11 {

CGLXExposeHelper::CGLXExposeHelper(CX11Window *pWindow)
    :   mWindow(pWindow)
{
}

CGLXExposeHelper::~CGLXExposeHelper()
{
}

img::CGC *CGLXExposeHelper::Prepare(CWindow &pWindow,const CRegion &pRegion,bool pClear)
{
    if(!mGC) mGC.reset(new gl::COpenGLGC(new CGLXContext(mWindow)));

    mGC->MakeCurrent();

    if(glGetError()!=GL_NO_ERROR)
        msg_warn() << "OpenGL context has error set in Prepare\n";

    CSize_d lSize=mWindow->GetSize();
    CRect_d lClientRect(pWindow.ClientRect()+pWindow.GetPosInTopLevel());
    CRect_d lRect(lClientRect.l,lSize.y-lClientRect.b,lClientRect.r,lSize.y-lClientRect.t);
    glDrawBuffer(GL_BACK);
    gl::viewport(lRect);
    mGC->SetExposeSize(lClientRect.Size());

    if(pClear)
    {
        gl::scissor(lRect);
        gl::clear_color(pWindow.BackColor());
        glClearDepth(1);
        glEnable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glDisable(GL_SCISSOR_TEST);
    }
    
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
    glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE);
    glPixelStorei(GL_UNPACK_ALIGNMENT,1);

    mGC->ResetState();
    return mGC.get();
}

void CGLXExposeHelper::Commit(const CRegion &pRegion)
{
    if(glGetError()!=GL_NO_ERROR)
        msg_warn() << "OpenGL context has error set in Commit\n";
    
    if(pRegion.empty()) return;
    
    CSize_d lSize=mWindow->GetSize();

    mGC->MakeCurrent();
    mGC->SwapBuffers(pRegion,lSize.y);
    
    if(glGetError()!=GL_NO_ERROR)
        msg_warn() << "OpenGL context has error set after Commit\n";
}

/*namespace x11*/ } /*namespace gui*/ } /*namespace buola*/ }
